package com.cskaoyan.javase.oop1._11static._0introduction._1new;

/**
 * 引例：
 * 练习：
 * 	创建一个学生类，用来描述我们班全体同学，要求
 * 		属性：姓名，性别，年龄，学号，学校信息
 * 		行为：吃饭，学习
 *
 * 创建多个Student对象，他们的属性取值可以不同，会发现什么问题呢？
 * 显然，我们会发现以下问题：
 *
 * 1. 无论创建多少Student对象，由于该类描述的是我们班全体同学，他们的班级信息实际上是一样的
 * 2. 创建多次对象，需要重复的给一个属性赋相同的值，这是很麻烦的，不方便的。
 * 3. 学校信息这个属性实质上应该是被全体同学所共有的属性，而不是独属于某个对象的。
 *
 * 所以，按照我们以往定义成员变量的方法来完成这个案例，是可以改进的。
 * 考虑如何改进？
 * 1. 可以把成员变量schoolName中直接显式赋值为“王道训练营”或者直接写死构造方法
 *    - 这样确实可以实现功能，但是没有从根本上解决问题，问题3依然存在
 *    - 学校信息这个属性在每一个对象当中都存在，有点浪费内存空间
 *    - 最重要的，我们在设计类的时候其实已经知道这个属性，是全体对象都有，不应该属于某个对象。
 *
 * - 我们希望这个属性不是属于某一个对象的，而是一种类的特征，是属于类的，属于全体对象所共享的
 *
 * 2. 上述改进不是我们最理想的改进方式，考虑以下改进：
 *    在内存中找一块区域，让该类的每个对象都共用/共享这片区域，把SchoolName属性放进去
 *
 *      于是：
 *      - SchoolName从对象独有的成员变量变成全体对象所共享的一种变量
 *      - 这样做既节省空间，减少了初始化成员变量的时间损耗
 *    - 最重要的体现了该属性属于类，属于全体对象共享的特点
 *
 * 成员变量成员方法是属于对象的，而现在我们需要一种属于类的变量和方法，它们就是static修饰的成员变量和成员方法。称之为静态成员方法和静态成员变量。统称静态成员
 * 当然普通的成员变量和方法，称之为成员或者普通成员。
 *
 * static修饰成员变量就是一个静态成员变量
 * 语法:
 * [访问权限修饰] static 数据类型 变量名;
 * 静态成员变量是属于类的,它不应该使用对象名点去访问,应该使用类名点去访问
 * 因为是属于类的,所以它不依赖于对象,完全独立于对象而存在
 * 静态成员变量和成员变量一样,都具有默认值,默认值是一样的
 *
 * static修饰成员方法就是一个静态成员方法
 * 语法:
 * [访问权限修饰符] static 返回值类型 方法名(形参列表){
 *     // 方法体
 * }
 * 静态成员方法也属于类,同样不依赖于对象创建访问,而是可以直接用类名点去访问
 * 特殊的,如果在同类中,可以直接省略类名,直接用方法名去调用.
 *
 * @since 10:46
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        /*WangDaoStudent s1 = new WangDaoStudent("张三", "女", 18, 1);
        WangDaoStudent s2 = new WangDaoStudent("李四", "女", 28, 2);
        // Static member 'com.cskaoyan.javase.oop1._11static._0introduction._1new.WangDaoStudent.schoolName' accessed via instance reference
        // 警告: 你正在通过一个对象引用 去访问静态成员
        System.out.println(s1.schoolName);
        s1.schoolName = "Java38th";
        System.out.println(s2.schoolName);*/

        System.out.println(WangDaoStudent.schoolName);

        WangDaoStudent.test();
        Demo.test();
    }
    public static void test(){}
}

class WangDaoStudent {
    String name;
    // 成员变量性别的定义
    /*
        性别属性的定义一般有两种方式：
            1.String/char gender/sex
            2.boolean isMale/isFemale
        我们建议使用方式一，不要使用isXxx的布尔类型
     */
    String gender;
    int age;
    int stuId;
    static String schoolName;

    public void eat() {
        System.out.println("干饭!");
    }

    public void study() {
        System.out.println("吃饱了学习！");
    }

    public WangDaoStudent(String name, String gender, int age, int stuId) {
        this.name = name;
        this.gender = gender;
        this.age = age;
        this.stuId = stuId;
    }

    public static void test(){}
}